home *** CD-ROM | disk | FTP | other *** search
- /* Support code for C column in Micro C issue #42
-
- Module: GlobEnv (Global Environment Access)
-
- Version: 1.02
- Date: April 11, 1988
-
- Compilers: Microsoft C v5.10
- Turbo C 1.5
- Datalight/Zortech Optimum-C (requires -a compiler switch)
-
- Environment: generic MS-DOS, version 2.1 and higher
-
- Allows direct access to the global (system) environment. This module
- has been tested with MS-DOS versions 2.11, 3.10, 3.2x, and 3.30.
-
- Copyright (c) 1988 by Scott Robert Ladd.
- This source-code file is released for non-commercial use by anyone
- who wants to use it. No warranties are expressed or implied.
- */
-
- #include "stddef.h"
- #include "string.h"
-
- #define TRUE -1
- #define FALSE 0
-
- /* external pointer to Program Segment Prefix (PSP) */
- extern unsigned _psp;
-
- /* structures for PSP and DOS Memory Control Block (MCB) */
- typedef struct
- {
- char fill1[22];
- unsigned parent_seg; /* segment of the parent of the current program */
- char fill2[20];
- unsigned env_seg; /* environment segment for current program */
- }
- PSP;
-
- /* This structure needs to be compiled exactly as shown -- no aligning! */
- /* The pack() pragma ensures Microsoft C will byte-align this structure. */
- /* Since most compilers have no such pargma, this module must be compiled */
- /* with BYTE alignment. This goes for Turbo C and Datalight C. */
- #pragma pack(1)
- typedef struct
- {
- char indicator; /* indicates whether this block is in chain */
- unsigned PSP_seg; /* the PSP segment of this block's owner */
- unsigned block_len; /* the size (in paragraphs) of this block */
- }
- MCB;
- #pragma pack()
-
- /* global variables */
- static char far *envptr; /* pointer to first byte of global env. */
- static unsigned int envlen; /* length of global environment */
- static int initdone=FALSE; /* indicates whether the module is initialized */
-
- /* function prototypes */
- char *getgenv(char *varname);
- int putgenv(char *varname, char *vartext);
- int delgenv(char *varname);
-
- static void findgenv(void);
-
- /*
- getgenv : Returns a pointer to the value of the environment variable
- pointed to by varname. If the string is not found, NULL is
- returned. Note that each call to this function erases the
- array s, destroying any previous variable value.
- */
- char *getgenv(char *varname)
- {
- char far *e;
- char *v;
- static char s[128];
- register int i;
-
- /* has the module been initialized? If not, do it! */
- if (!initdone)
- findgenv();
-
- e = envptr;
-
- /* search for varname */
- while (*e)
- {
- v = varname;
- for (;(*e == *v) && (*e != '=') && *e && *v; ++e, ++v);
- if ((!*v) && (*e == '=')) /* varname found */
- {
- ++e;
- /* copy value to s */
- /* can't use strcpy() due to possibly different-sized pointers */
- for (i = 0; (i < 127) && *e; ++i)
- {
- s[i] = *e;
- ++e;
- }
- if (i < 127)
- s[i] = 0;
- return s; /* contains value of varname */
- }
- /* skip to the next environment variable */
- for (; *e; ++e);
- ++e;
- }
-
- /* varname wasn't found */
- return NULL;
- }
-
- /*
- putgenv : Varstring is built from the variable name (varname) and vartext.
- Stores the varstring into the current global environment.
- Returns -1 if there is not enough room in the environment for
- the new string; otherwise, 0 is returned.
- */
- int putgenv(char *varname, char *vartext)
- {
- char far *e;
- unsigned int l;
- char varstring[256];
- char *v;
-
- /* has the module been initialized? If not, do it! */
- if (!initdone)
- findgenv();
-
- /* make a complete environment string from the components given */
- strcpy(varstring,varname);
- strupr(varstring); /* make sure the name of the variable is uppercase */
- strcat(varstring,"=");
- strcat(varstring,vartext);
-
- /* delete any existing variables of the same name */
- delgenv(varname);
-
- /* find the end of the current variables (mark by two nulls) */
- for (e = envptr, l = 0; !(!*e && !*(e+1)); ++e, ++l);
-
- /* get the amount of remaining space */
- l = envlen - l;
-
- /* if the new variable won't fit, return an error */
- if (l < strlen(varstring))
- return -1;
-
- v = varstring;
- /* otherwise, copy varstring onto the end of the current environment */
- for (++e; *v; *e++ = *v++);
-
- /* and end the environment with two NUL bytes */
- *e = 0;
- ++e;
- *e = 0;
-
- /* it worked! */
- return 0;
- }
-
- /*
- delgenv : Deletes a global environment variable.
- */
- int delgenv(char *varname)
- {
- char far *e1; /* used in search & marks beginning of next variable */
- char far *e2; /* marks beginning of the variable */
- char *v; /* varname pointer used in serach */
- int searching = TRUE; /* flag to indicate serach end */
-
- /* has the module been initialized? If not, do it! */
- if (!initdone)
- findgenv();
-
- e1 = envptr;
-
- /* find the beginning of the variable to be deleted */
- while (*e1 && searching)
- {
- v = varname;
- e2 = e1;
- for (;(*e1 == *v) && (*e1 != '=') && *e1 && *v; ++e1, ++v);
- if ((!*v) && (*e1 == '='))
- searching = FALSE; /* the variable we want was found! */
- for (; *e1; ++e1);
- ++e1;
- }
-
- /* if varname wasn't found, return with an error */
- if (!*e1 && searching)
- return -1;
-
- /* otherwise, copy the remainder of the environment over varname */
- for (; !(!*e1 && !*(e1+1)); *e2++ = *e1++);
-
- /* end the environment with double NUL bytes */
- *e2 = 0;
- ++e2;
- *e2 = 0;
-
- /* it worked */
- return 0;
- }
-
- /*
- findgenv : This function must be called before the other functions
- in the module will work.
- */
- static void findgenv()
- {
- PSP far *curPSP; /* current PSP */
- PSP far *parPSP; /* parent PSP */
- MCB far *parMCB; /* parent MCB */
- MCB far *envMCB; /* environment MCB */
-
- /* set pointers to the PSPs of the current program and its parent */
- curPSP = (PSP far *)((long)_psp << 16);
- parPSP = (PSP far *)((long)(curPSP->parent_seg) << 16);
-
- if (parPSP->env_seg == 0)
- {
- /* the environment is in the block after the parent program */
- parMCB = (MCB far *)((long)parPSP - 0x10000L);
- envptr = (char far *)((long)parPSP + 0x10000L + ((long)parMCB->block_len << 16));
- }
- else
- /* we have a direct pointer to the environment */
- envptr = (char far *)((long)(parPSP->env_seg) << 16);
-
- /* the MCB of the environment is one segment lower in memory */
- envMCB = (MCB far *)((long)(envptr) - 0x10000L);
-
- /* save the length of the environment */
- envlen = envMCB->block_len;
-
- /* make sure the other functions know that findgenv is done */
- initdone = TRUE;
- }
-